import unittest
import mox
import tactics
from api import gameinfo
from api.vector2 import Vector2

class TestCommander(unittest.TestCase):

    def setUp(self):
      self.commander = tactics.TZCommander()
      self.commander.game = gameinfo.GameInfo
      self.commander.game.team = gameinfo.TeamInfo("a")
      self.commander.game.team.flag = gameinfo.FlagInfo("x")
      self.commander.game.team.flag.position = Vector2(1,1)
      self.commander.game.team.flagScoreLocation = Vector2(1,1)
      self.commander.game.enemyTeam = gameinfo.TeamInfo("b")
      self.commander.game.enemyTeam.flag = gameinfo.FlagInfo("x")
      self.commander.game.enemyTeam.flag.position = Vector2(1,1)
      self.commander.game.enemyTeam.flagScoreLocation = Vector2(1,1)
      self.commander.level = gameinfo.LevelInfo
      self.commander.level.width = 10
      self.commander.level.height = 10
      self.commander.game.team.members = []
      self.commander.game.enemyTeam.members = []
      self.commander.game.bots = {}
      self.commander.game.match = gameinfo.MatchInfo()
      for i in range(4):
        bot = gameinfo.BotInfo("bot %d" % i)
        bot.health = 100
        bot.position = Vector2(i,i)
        self.commander.game.team.members.append(bot)
        self.commander.game.bots[bot.name] = bot
        bot = gameinfo.BotInfo("enemy bot %d" % i)
        bot.health = 100
        bot.position = Vector2(i*2,i*2)
        self.commander.game.enemyTeam.members.append(bot)
        
      self.commander.game.bots_alive = self.commander.game.team.members
      
      self.mox = mox.Mox()
      self.mox.StubOutWithMock(self.commander.level, "findNearestFreePosition")
      self.commander.level.findNearestFreePosition(mox.IsA(Vector2)).MultipleTimes().AndReturn(Vector2(1,1))
      self.mox.ReplayAll()
      self.commander.initialize()
      self.mox.VerifyAll()
      self.mox.UnsetStubs()
      self.mox = mox.Mox()

    def tearDown(self):
      self.mox.VerifyAll()
      self.mox.UnsetStubs()

    def test_gen_inputs(self):
      self.commander.gen_inputs()
      self.assertEqual(self.commander.my_alive_pct, 1)
      self.assertEqual(self.commander.opp_alive_pct, 1)
      self.assertFalse(self.commander.i_have_flag)
      self.assertFalse(self.commander.opp_has_flag)
      self.commander.game.team.members[0].health = 0
      self.commander.game.enemyTeam.members[0].health = 0
      self.commander.game.enemyTeam.members[1].health = 0
      self.commander.game.enemyTeam.members[0].seenlast = 0
      self.commander.game.enemyTeam.members[1].seenlast = 0
      self.commander.gen_inputs()
      self.assertEqual(self.commander.my_alive_pct, 0.75)
      self.assertEqual(self.commander.opp_alive_pct, 0.5)
      self.commander.game.team.flag.carrier = "A"
      self.commander.gen_inputs()
      self.assertTrue(self.commander.opp_has_flag)
      self.assertFalse(self.commander.i_have_flag)
      self.commander.game.team.flag.carrier = None
      self.commander.game.enemyTeam.flag.carrier = "B"
      self.commander.gen_inputs()
      self.assertFalse(self.commander.opp_has_flag)
      self.assertTrue(self.commander.i_have_flag)

    def test_reassign_roles(self):
      self.mox.StubOutWithMock(self.commander, "MyIssue")
      self.commander.MyIssue(mox.IgnoreArg(), mox.IsA(gameinfo.BotInfo), mox.IsA(Vector2), mox.IgnoreArg()).MultipleTimes()
      self.mox.ReplayAll()
      self.commander.reassign_roles({tactics.TZCommander.GO_ENEMY_FLAG:[4,]})
      bots = self.commander.game.team.members
      for b in bots:
        self.assertTrue(self.commander.current_orders[b.name], (tactics.TZCommander.GO_ENEMY_FLAG,))
      self.commander.reassign_roles({tactics.TZCommander.GO_ENEMY_FLAG:[2,], tactics.TZCommander.GO_GOAL:[2,]})
      flag_count = 0
      goal_count = 0
      for b in bots:
        if self.commander.current_orders[b.name][0] == tactics.TZCommander.GO_ENEMY_FLAG:
          flag_count +=1
        if self.commander.current_orders[b.name][0] == tactics.TZCommander.GO_GOAL:
          goal_count +=1
      self.assertEquals(flag_count, 2)
      self.assertEquals(goal_count, 2)
      self.commander.reassign_roles({tactics.TZCommander.GO_ENEMY_FLAG:[3,], tactics.TZCommander.PATROL:[1,]})
      flag_count = 0
      goal_count = 0
      patrol_count = 0
      for b in bots:
        if self.commander.current_orders[b.name][0] == tactics.TZCommander.GO_ENEMY_FLAG:
          flag_count +=1
        if self.commander.current_orders[b.name][0] == tactics.TZCommander.GO_GOAL:
          goal_count +=1
        if self.commander.current_orders[b.name][0] == tactics.TZCommander.PATROL:
          patrol_count +=1
      self.assertEquals(flag_count, 3)
      self.assertEquals(goal_count, 0)
      self.assertEquals(patrol_count, 1)
      for i in range(len(bots)):
        bots[i].health = 100 - i

      self.commander.reassign_roles({tactics.TZCommander.GO_GOAL:[2,lambda b: -b.health], tactics.TZCommander.GO_ENEMY_GOAL:[2,]})
      self.assertEquals(self.commander.current_orders[bots[0].name][0], tactics.TZCommander.GO_GOAL)
      self.assertEquals(self.commander.current_orders[bots[1].name][0], tactics.TZCommander.GO_GOAL)
      self.assertEquals(self.commander.current_orders[bots[2].name][0], tactics.TZCommander.GO_ENEMY_GOAL)
      self.assertEquals(self.commander.current_orders[bots[3].name][0], tactics.TZCommander.GO_ENEMY_GOAL)

      for i in range(len(bots)):
        bots[i].health = 50 + i

      self.commander.reassign_roles({tactics.TZCommander.PATROL:[2,lambda b: -b.health], tactics.TZCommander.GO_ENEMY_FLAG:[2,]})
      self.assertEquals(self.commander.current_orders[bots[0].name][0], tactics.TZCommander.GO_ENEMY_FLAG)
      self.assertEquals(self.commander.current_orders[bots[1].name][0], tactics.TZCommander.GO_ENEMY_FLAG)
      self.assertEquals(self.commander.current_orders[bots[2].name][0], tactics.TZCommander.PATROL)
      self.assertEquals(self.commander.current_orders[bots[3].name][0], tactics.TZCommander.PATROL)

    def test_order_tracking(self):
      bot = self.commander.game.team.members[0]
      self.mox.StubOutWithMock(self.commander, "MyIssue")
      self.commander.MyIssue(mox.IgnoreArg(), mox.IsA(gameinfo.BotInfo), mox.IsA(Vector2), mox.IgnoreArg()).MultipleTimes()
      self.mox.ReplayAll()
      self.commander.GoEnemyFlag(bot)
      self.assertEquals(self.commander.current_orders[bot.name], ("GoEnemyFlag",{}))
      self.commander.GoOurFlag(bot)
      self.assertEquals(self.commander.current_orders[bot.name], ("GoOurFlag",{}))
      self.commander.GoGoal(bot)
      self.assertEquals(self.commander.current_orders[bot.name][0], "GoGoal")
      self.commander.GoEnemyGoal(bot)
      self.assertEquals(self.commander.current_orders[bot.name][0], "GoEnemyGoal")
      self.commander.Patrol(bot)
      self.assertEquals(self.commander.current_orders[bot.name], ("Patrol", {'target': Vector2(1,1)}))
      self.commander.DefensePatrol(bot)
      self.assertEquals(self.commander.current_orders[bot.name], ("DefensePatrol", {'target':Vector2(1,1)}))
      self.commander.AttackBot(bot, self.commander.game.enemyTeam.members[0])
      self.assertEquals(self.commander.current_orders[bot.name],
                        ("AttackBot", {'name': 'enemy bot 0', 'pos': (0.0, 0.0)}))

    def test_vector(self):
      bot = Vector2(1,0)
      flag = Vector2(10,-2)
      goal = Vector2(2,0)
      half = bot.midPoint(flag)
      interceptor = (bot - flag).normalized().perpendicular()
      interceptor = interceptor * half.distance(goal)
      p = half
      r = interceptor
      q = flag
      s = goal - flag
      u = (q - p).crossProduct(r) / r.crossProduct(s)
      print u
      print q + s * u
      

if __name__ == '__main__':
    unittest.main()
